/**
 * @ignore
 * manage a list of single-select options
 * @author yiminghe@gmail.com
 */

var $ = require('node');
var MenuButton = require('./control');
var util = require('util');

function getSelectedItem(self) {
    var menu = self.get('menu'),
        cs = menu.children || menu.get && menu.get('children') || [],
        value = self.get('value'),
        c,
        i;
    for (i = 0; i < cs.length; i++) {
        c = cs[i];
        if (getItemValue(c) === value) {
            return c;
        }
    }
    return null;
}

// c: Option
// c.get('value')
// c: Object
// c.value
function getItemValue(c) {
    var v;
    if (c) {
        if (c.get) {
            if ((v = c.get('value')) === undefined) {
                v = c.get('textContent') || c.get('content');
            }
        } else {
            if ((v = c.value) === undefined) {
                v = c.textContent || c.content;
            }
        }
    }
    return v;
}

function deSelectAllExcept(self) {
    var menu = self.get('menu'),
        value = self.get('value'),
        cs = menu && menu.get && menu.get('children');
    util.each(cs, function (c) {
        if (c && c.set) {
            c.set('selected', getItemValue(c) === value);
        }
    });
}

// different from menubutton by highlighting the currently selected option on open menu.
function _handleMenuShow(e) {
    var self = this,
        selectedItem = getSelectedItem(self),
        m = self.get('menu');
    if (e.target === m) {
        var item = selectedItem || m.getChildAt(0);
        if (item) {
            item.set('highlighted', true);
        }
        // 初始化选中
        if (selectedItem) {
            selectedItem.set('selected', true);
        }
    }
}

function _updateCaption(self) {
    var item = getSelectedItem(self),
        textContent = item && (item.textContent || item.get && item.get('textContent')),
        content = item && (item.content || item.get && item.get('content'));
    // 可能设置到 select content 的内容并不和 menuitem 的内容完全一致
    self.set('content', textContent || content || self.get('defaultCaption'));
}

/*
 Handle click on drop down menu.
 Set selected menu item as current selectedItem and hide drop down menu.
 Protected, should only be overridden by subclasses.
 */
function handleMenuClick(e) {
    var self = this,
        target = e.target;
    if (target.isMenuItem) {
        var newValue = getItemValue(target),
            oldValue = self.get('value');
        self.set('value', newValue);
        if (newValue !== oldValue) {
            self.fire('change', {
                prevVal: oldValue,
                newVal: newValue
            });
        }
    }
}

/**
 * Select component which supports single selection from a drop down menu
 * with semantics similar to native HTML select.
 * xclass: 'select'.
 * @class KISSY.MenuButton.Select
 * @extends KISSY.MenuButton
 */
var Select = MenuButton.extend({
        bindUI: function () {
            this.on('click', handleMenuClick, this);
            this.on('show', _handleMenuShow, this);
        },

        /**
         * Removes all menu items from current select, and set selectedItem to null.
         *
         */
        removeItems: function () {
            var self = this;
            self.callSuper.apply(self, arguments);
            self.set('value', null);
        },

        /**
         * Remove specified item from current select.
         * If specified item is selectedItem, then set selectedItem to null.
         * @param c {KISSY.MenuButton.Option} Existing menu item.
         * @param [destroy=true] {Boolean} Whether destroy removed menu item.
         */
        removeItem: function (c, destroy) {
            var self = this;
            self.callSuper(c, destroy);
            if (c.get('value') === self.get('value')) {
                self.set('value', null);
            }
        },

        _onSetValue: function () {
            var self = this;
            deSelectAllExcept(self);
            _updateCaption(self);
        },

        _onSetDefaultCaption: function () {
            _updateCaption(this);
        }
    },
    {
        ATTRS: {

            /**
             * Get current select 's value.
             */
            value: {
            },

            /**
             * Default caption to be shown when no option is selected.
             * @type {String}
             */
            defaultCaption: {
                value: ''
            },

            collapseOnClick: {
                value: true
            }
        },

        /**
         * Generate a select component from native select element.
         * @param {HTMLElement} element Native html select element.
         * @param {Object} cfg Extra configuration for current select component.
         * @member KISSY.MenuButton.Select
         */
        decorate: function (element, cfg) {
            element = $(element);
            cfg = cfg || {};
            cfg.elBefore = element;

            var name,
                allItems = [],
                select,
                selectedItem = null,
                curValue = element.val(),
                options = element.all('option');

            options.each(function (option) {
                var item = {
                    xclass: 'option',
                    content: option.text(),
                    elCls: option.attr('class'),
                    value: option.val()
                };
                if (curValue === option.val()) {
                    selectedItem = {
                        content: item.content,
                        value: item.value
                    };
                }
                allItems.push(item);
            });

            cfg.menu = cfg.menu || cfg.menuCfg || {};
            cfg.menu.children = allItems;
            delete cfg.menuCfg;

            select = new Select(util.mix(cfg, selectedItem)).render();

            if ((name = element.attr('name'))) {
                var input = $('<input' +
                    ' type="hidden"' +
                    ' name="' + name + '" value="' + curValue + '">')
                    .insertBefore(element, undefined);

                select.on('afterValueChange', function (e) {
                    input.val(e.newVal || '');
                });
            }

            element.remove();
            return select;
        },
        xclass: 'select'

    });

module.exports = Select;

/*
 TODO
 how to emulate multiple ?
 */